package xin.nick.bean;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @author Nick
 * @date 2021/7/18
 * @description
 */
@Activate(group = {CommonConstants.CONSUMER})
public class TpMonitorFilter implements Filter, Runnable {

    private static final Logger logger =
            LoggerFactory.getLogger(TpMonitorFilter.class);

    private static List<CallInfo> callInfoList = new ArrayList<>();

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long startTime = System.currentTimeMillis();
        try {
            return invoker.invoke(invocation);
        } finally {
            // 拦截器拦截每次的请求时长,并保存
            callInfoList.add(new CallInfo(startTime,
                    System.currentTimeMillis() - startTime,
                    invocation.getMethodName()));
        }
    }

    @Override
    public void run() {

        try {
            // 调用时间list
            List<Long> method1Times = new ArrayList<>();
            List<Long> method2Times = new ArrayList<>();
            List<Long> method3Times = new ArrayList<>();

            // 统计时间范围
            long currentTime = System.currentTimeMillis();
            long lastTime = currentTime - (60 * 1000);

            // 遍历列表,并存到treeMap,并计算, 同时剔除超过时间的
            Iterator<CallInfo> iterator = callInfoList.iterator();
            while (iterator.hasNext()) {
                CallInfo callInfo = iterator.next();
                if (callInfo.getTimestamp() < lastTime) {
                    iterator.remove();
                } else if (callInfo.getTimestamp() < currentTime) {
                    if ("method1".equals(callInfo.getMethodName())) {
                        method1Times.add(callInfo.getCallTime());
                    } else if ("method2".equals(callInfo.getMethodName())) {
                        method2Times.add(callInfo.getCallTime());
                    } else if ("method3".equals(callInfo.getMethodName())) {
                        method3Times.add(callInfo.getCallTime());
                    }
                }
            }

            // 排序
            Collections.sort(method1Times);
            Collections.sort(method2Times);
            Collections.sort(method3Times);

            logger.info("性能监测....");
            if (method1Times.size() > 0) {
                logger.info("method1, 调用次数: {}, TP90: {}, TP99: {}", method1Times.size(),
                        method1Times.get((int) (method1Times.size() * 0.9)),
                        method1Times.get((int) (method1Times.size() * 0.99)));
            }
            if (method2Times.size() > 0) {
                logger.info("method2, 调用次数: {}, TP90: {}, TP99: {}", method1Times.size(),
                        method2Times.get((int) (method2Times.size() * 0.9)),
                        method2Times.get((int) (method2Times.size() * 0.99)));
            }
            if (method3Times.size() > 0) {
                logger.info("method3, 调用次数: {}, TP90: {}, TP99: {}", method3Times.size(),
                        method3Times.get((int) (method3Times.size() * 0.9)),
                        method3Times.get((int) (method3Times.size() * 0.99)));
            }
        } catch (Exception e) {
            logger.error("性能监测挂了, ", e);
        }
    }
}
